package model;

import common.Car;
import view.Boundary;
import fields.Ownable;
import fields.Street;

public class Player {
	private String name;
	private int color;
	private int position; //indexed by 1
	private Account account;
	private Ownable[] owned;
	private int jailedTime;
	private boolean isPlaying;
	private int pardonCardCounter;
	
	public Player(String name, int color, int balance) {
		super();
		this.name = name;
		this.color = color;
		this.account = new Account(balance);
		this.owned = new Ownable[40];
		this.jailedTime = -1;
		this.isPlaying = true;
		this.pardonCardCounter = 0;
		Boundary.addPlayer(getName(), getBalance());
		this.setPosition(1);
	}
	@Override
	public String toString() {
		String str = "[";
		for(Ownable o : this.owned){
			if(o != null) str += o.getName() + ", ";
		}
		if(str.contains(", ")){
			str = str.substring(0, str.length()-2);
		}
		str += "]";
		return "Player [name=" + this.name + ", color=" + this.color + ", account="
				+ this.account + ", owned=" + str +
				" position=" + this.position;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj) return true;
		if (obj == null) return false;
		if (getClass() != obj.getClass()) return false;
		Player other = (Player) obj;
		if (this.name == null) {
			if (other.name != null)
				return false;
		} else if (!this.name.equals(other.name))
			return false;
		return true;
	}
	public String getName() {
		return this.name;
	}
	public int getColor() {
		return this.color;
	}
	/**
	 * 1-40
	 * @return players position
	 */
	public int getPosition() {
		return this.position;
	}
	/**
	 * @param position 1-40
	 */
	public void setPosition(int position) {
		while(position < 1){ position += 40; }
		while(position > 40) { position -= 40; }
		this.position = position;
		Boundary.setCar(this.position, this.name);
	}
	public int getBalance(){
		return this.account.getBalance();
	}
	public boolean withdraw(int amount){
		boolean result = this.account.withdraw(amount);
		Boundary.setBalance(this.name, this.account.getBalance());
		return result;
	}
	public boolean deposit(int amount){
		boolean result = this.account.deposit(amount);
		Boundary.setBalance(this.name, this.account.getBalance());
		return result;
	}
	public boolean transfer(Player otherPlayer, int amount){
		boolean result = this.account.transfer(otherPlayer, amount);
		Boundary.setBalance(this.name, this.account.getBalance());
		return result;
	}
	public Ownable[] getOwned() {
		return this.owned;
	}
	public int getJailedTime() {
		return this.jailedTime;
	}
	public void incrementJailedTime(){
		this.jailedTime++;
	}
	public void resetJailedTime(){
		this.jailedTime = -1;
	}
	public int calculatePlayerWorth(){
		//TODO Card worth?
		int worth = this.account.getBalance();
		for(Ownable o : this.owned){
			if(o != null && !o.isPawned()) {	
				worth += o.getPrice() / 2; //Only pawn value
				if(o instanceof Street){
					Street s = (Street)o;
					worth += s.getHouseCount() * s.getHousePrice();
				}
			}
		}
		return worth;
	}
	public void addField(Ownable ownable) {
		this.owned[ownable.getNumber()-1] = ownable;
	}
	public boolean isPlaying(){
		return this.isPlaying;
	}
	public void setIsPlaying(boolean isPlaying){
		this.isPlaying = isPlaying;
	}
	public boolean hasPardonCard(){
		return this.pardonCardCounter > 0;
	}
	public void addPardonCard(){
		this.pardonCardCounter++;
	}
	public void removePardonCard(){
		this.pardonCardCounter--;
	}
}